package handler

import (
	"encoding/json"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"

	"log"
	"message-queue_0826/global"
	"strconv"
)

type ChatClient struct {
	Id   int
	Conn *websocket.Conn
	Send chan []byte
}

type ChatClientManage struct {
	Client map[string]*ChatClient
	ComeIn chan *ChatClient
	GoOut  chan *ChatClient
}

type ChatMessage struct {
	Form    int    `json:"form"`
	Content string `json:"content"`
	TO      int    `json:"to"`
}

var ChatManage = ChatClientManage{
	Client: make(map[string]*ChatClient),
	ComeIn: make(chan *ChatClient),
	GoOut:  make(chan *ChatClient),
}

func CharMessage(c *gin.Context) {

	id, _ := strconv.Atoi(c.Query("user_id"))

	conn, err := global.Upgrader.Upgrade(c.Writer, c.Request, nil)

	if err != nil {
		log.Println("Upgrader.Upgrade", err)
		return
	}

	Client := ChatClient{
		Id:   id,
		Conn: conn,
		Send: make(chan []byte),
	}

	ChatManage.ComeIn <- &Client
	go ReadChat(&Client)
	go WriteChat(&Client)
}

func ReadChat(p *ChatClient) {
	defer func() {
		ChatManage.GoOut <- p
		p.Conn.Close()
	}()
	for {
		_, message, err := p.Conn.ReadMessage()
		if err != nil {
			log.Println("Conn.ReadMessage", err)
			return
		}

		var msg ChatMessage
		log.Println("read message", string(message))

		err = json.Unmarshal(message, &msg)

		toClient := ChatManage.Client[strconv.Itoa(msg.TO)]

		if toClient != nil {
			toClient.Send <- message
		}
	}
}

func WriteChat(p *ChatClient) {
	for {
		select {
		case message, ok := <-p.Send:
			if !ok {
				p.Conn.WriteMessage(websocket.CloseMessage, []byte{})
			}

			log.Println("WriteMessage", string(message))

			p.Conn.WriteMessage(websocket.TextMessage, message)
		}
	}
}

func (m *ChatClientManage) Start() {
	for {
		select {
		case Client := <-m.ComeIn:
			m.Client[strconv.Itoa(Client.Id)] = Client

		case Client := <-m.GoOut:
			delete(m.Client, strconv.Itoa(Client.Id))
		}
	}
}
